#include "event_loop.h"
#include "sys/eventfd.h"
#include "unistd.h"


EventLoop::EventLoop():
    threadID_(std::this_thread::get_id()),
    wakeupFd_(eventfd(0, 0)),
    wakeupChannel_(new Channel(this, wakeupFd_)),
    poller_(new Poller())
{
    wakeupChannel_->SetReadCallBack(std::bind(&EventLoop::HandleRead, this));
    wakeupChannel_->EnableReading();
}

EventLoop::~EventLoop(){
    // wakeupChannel_->disableAll();
    // wakeupChannel_->remove();
    close(wakeupFd_);
}

bool EventLoop::IsInLoopThread()
{
    std::thread::id threadID = std::this_thread::get_id();
    if(threadID_ == threadID){
        return true;
    }
    return false;
}

void EventLoop::Loop()
{
    std::vector<Channel*> activeChannels;
    while(true){
        poller_->Poll(activeChannels);
        if(activeChannels.empty()){
            continue;
        }
        for(auto* channel : activeChannels){
            channel->HandleEvents();
        }
        // clear只会清空队列，不会回收已经申请的空间 
        activeChannels.clear();
        DoPendingFunctors();
    }
}

void EventLoop::RunInLoop(TaskCallBack cb)
{
    if(IsInLoopThread()){
        cb();
    }else{
        QueueInLoop(std::move(cb));
    }
}

void EventLoop::QueueInLoop(TaskCallBack cb)
{
    {
    MutexGuard mutextGuard(mutex_);
    pendingFunctors_.push_back(std::move(cb));
    }
    
    // if (!IsInLoopThread() || callingPendingFuncotrs_){
        Wakeup();
    // }
}

void EventLoop::HandleRead()
{
  uint64_t one = 1;
  ssize_t n = read(wakeupFd_, &one, sizeof one);
}

void EventLoop::Wakeup()
{
  uint64_t one = 1;
  ssize_t n = write(wakeupFd_, &one, sizeof one);
}

void EventLoop::DoPendingFunctors()
{
  std::vector<TaskCallBack> functors;
//   callingPendingFunctors_ = true;

  {
  MutexGuard lock(mutex_);
  functors.swap(pendingFunctors_);
  }

  for (const TaskCallBack& functor : functors)
  {
    functor();
  }
//   callingPendingFunctors_ = false;
}

void EventLoop::UpdateChannel(Channel* channel)
{
//   assert(channel->ownerLoop() == this);
//   assertInLoopThread();
  poller_->UpdateChannel(channel);
}

// Q:removeChannel 什么时候被调用？？
// void EventLoop::RemoveChannel(Channel* channel)
// {
//   assert(channel->ownerLoop() == this);
//   assertInLoopThread();
//   if (eventHandling_)
//   {
//     assert(
//         currentActiveChannel_ == channel ||
//         std::find(activeChannels_.begin(), activeChannels_.end(), channel) == activeChannels_.end());
//   }
//   poller_->RemoveChannel(channel);
// }